package view{

	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundMixer;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;

	/**
	* Class to hanldle simple loading and playing back of sounds. This class also surfaces the sound
	* spectrum of the Flash player's current loaded sounds that can be used for visualizations.
	*/
	public class SoundController extends EventDispatcher {

		private var _timerSprite:Sprite;
		private var _playing:Boolean;
		private var _sound:Sound;
		private var _soundChannel:SoundChannel;

		/**
		* Constructor. This sets up an ENTER_FRAME listener on a sprite to be used to help
		* broadcast events when a sound is playing so that a visualization can update each frame.
		* If a file is passed to this constructor, it will be loaded and played.
		*
		* @param file The sound file to request.
		*/
		public function SoundController(file:String=null) {
			_timerSprite = new Sprite();
			_timerSprite.addEventListener(Event.ENTER_FRAME, onSpriteEnterFrame);
			if (file) {
				load(file);
			}
		}

		/**
		* Handler for ENTER_FRAME. If the sound is currently playing, a CHANGE event is dispatched.
		*
		* @param event Event dispatched by sprite.
		*/
		private function onSpriteEnterFrame(event:Event):void 
		{
			if (_playing) {
				dispatchEvent(new Event(Event.CHANGE));
			}
		}

		/**
		* Sets _playing flag to false to prevent further dispatch of CHANGE event.
		* Also dispatches COMPLETE event to listening objects.
		*
		* @param event Event dispatched by SoundController.
		*/
		private function onSoundComplete(event:Event):void 
		{
			_playing = false;
			dispatchEvent(event);
		}

		/**
		* Handler for an error when loading a sound file. Simply redispatches event.
		*
		* @param event Event dispatched by SoundController.
		*/
		private function onLoadError(event:Event):void {
			dispatchEvent(event);
		}

		/**
		* Attempts to load a sound file.
		*
		* @param file The sound file to load.
		*/
		public function load(file:String):void {
			_playing = false;
			_sound = new Sound();
			_sound.addEventListener(IOErrorEvent.IO_ERROR, onLoadError);
			try {
				_sound.load(new URLRequest(file));
				_soundChannel = _sound.play();
				_soundChannel.addEventListener(Event.SOUND_COMPLETE, onSoundComplete);
				_playing = true;
			} catch (e:Error) {
				trace(e.getStackTrace());
			}
		}

		/**
		* Returns a byte array containing the sound spectrum data of the loaded sounds playing in the 
		* Flash player. This will include ANY loaded sounds playing, since SoundMixer.computeSpectrum()
		* does not differentiate between channels.
		*
		* @param fftMode Whether to return frequency spectrum data or raw sound wave data.
		* @param stretchFactor The sampling rate used for the spectrum data.
		*
		* @return A byte array populated with sound spectrum data.
		*/
		public function getSoundSpectrum(fftMode:Boolean=true, stretchFactor:int=0):ByteArray {
			var spectrumData:ByteArray = new ByteArray();
			SoundMixer.computeSpectrum(spectrumData, fftMode, stretchFactor);
			return spectrumData;
		}

	}

}